package swissmap;

import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

import javax.imageio.ImageIO;

import swissmap.coordinates.CoConvert;
import swissmap.coordinates.SwissCoordinate;

public class Mapbuilder {

	private String curres;
	
	private int width;
	private int height;
	private int largest_f;
	private int smallest_f;
	private int largest_col;
	private int smallest_col;
	private String file;
	private boolean min;
	
	/**
	 * 
	 * @param curres
	 * @param min
	 */
	public Mapbuilder(String curres, boolean min){
		this.curres=curres;
		file=Constants.basePath+"raw"+File.separator+(Constants.map?"map":"ortho")+File.separator+curres+File.separator+""+curres+"-";
		this.min=min;
		
		getDim();
	}
	
	/**
	 * 
	 * @param builtMap, image generation
	 */
	public void buildMap_Control(boolean builtMap){
		
		int columns=2;
		int rows=2;
		
		int tmpWidth,w_save;//=(int)Math.ceil((double)width/(2*256))*256;
		int tmpHeight,h_save;//=(int)Math.ceil((double)height/(2*256))*256;//height/2;
		String nameExt;
		int row_from,row_to,col_from,col_to;
		
		if(curres.equals("50k")){
//			columns=2;
//			rows=2;
			columns=1;
			rows=1;
		}else if(curres.equals("25k")){
			columns=4;
			rows=4;
		}else if(curres.equals("20k")){
			columns=8;
			rows=8;
	
		}else if(curres.equals("10k")){
			columns=16;
			rows=16;
		
		}else{			
			columns=1;
			rows=1;
			//100k / 200k
		}
		
		
		tmpWidth=(int)Math.floor((double)width/(columns*256))*256;
		w_save=tmpWidth;
		tmpHeight=(int)Math.floor((double)height/(rows*256))*256;
		h_save=tmpHeight;
		
		for(int r=0;r<rows;r++){
			for(int c=0;c<columns;c++){
				nameExt=(c<10?"0"+c:c)+"-"+(r<10?"0"+r:r);
				
				col_from=smallest_col+(c*tmpWidth/256);
				if(c<columns-1){
					col_to=col_from+(tmpWidth/256)-1;
				}else{
					w_save=tmpWidth;
					tmpWidth=width-(c*tmpWidth);
					System.out.println(width+"   "+tmpWidth+"   "+c);
					col_to=largest_col;
				}
				
				row_from=smallest_f+(r*tmpHeight/256);
				if(r<rows-1){
					row_to=row_from+(tmpHeight/256)-1;
				}else{
					h_save=tmpHeight;
					tmpHeight=height-(r*tmpHeight);
					row_to=largest_f;
				}
				
				if(builtMap)
					buildMap(tmpWidth, tmpHeight, row_from, row_to, col_from, col_to, nameExt);
				System.out.println("     "+tmpWidth+" x "+tmpHeight);
				System.out.println("col: "+col_from+" "+col_to);
				System.out.println("row: "+row_from+" "+row_to);
				writeIMP(tmpWidth, tmpHeight, row_from, row_to, col_from, col_to, nameExt);
				tmpWidth=w_save;
				tmpHeight=h_save;
			}
		}
	}
	
	/**
	 * generate image file
	 * @param width
	 * @param height
	 * @param smallest_f
	 * @param largest_f
	 * @param smallest_col
	 * @param largest_col
	 * @param name_ext
	 */
	public void buildMap(int width, int height,int smallest_f,int largest_f,int smallest_col, int largest_col, String name_ext){
		//int dim[]=getMinDim(curres);
		//int dim[]=getMaxDim(curres);
		
	
		
//		System.out.println("small f "+smallest_f);
//		System.out.println("largest f "+largest_f);
		System.out.println("width "+width);
		System.out.println("height "+height);

		//
		BufferedImage map=new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
		
		try {
		
		for(int row=largest_f;row>smallest_f-1;row--){
			for(int col=smallest_col;col<=largest_col;col++){
				File f=new File(Constants.basePath+"raw"+File.separator+(Constants.map?"map":"ortho")+File.separator+curres+File.separator+Constants.intoToString(col)+File.separator+Constants.intoToString(row)+".jpeg");
				//System.out.println(f.getAbsolutePath());
				BufferedImage img;
				img = ImageIO.read(f);

				int w = img.getWidth(); 
				int h = img.getHeight();
				int[] rgbs = new int[w*h]; 
				img.getRGB(0, 0, w, h, rgbs, 0, w); 


//				public void setRGB(int startX,
//               int startY,
//               int w,
//               int h,
//               int[] rgbArray,
//               int offset,
//               int scansize)

				//System.out.println("  "+col+"  "+row);
				//System.out.println("  "+(col-smallest_col)*256+"  "+(largest_f-row)*256);
				map.setRGB((col-smallest_col)*256,(largest_f-row)*256, 256,256, rgbs,0,256); 
			}
		}
		
		File result=new File(file+name_ext+"."+Constants.fileFormat);
		//System.out.println(result.getParentFile().getAbsolutePath());
		result.getParentFile().mkdirs();
		
		ImageIO.write(map, Constants.fileFormat, result);
		System.out.println("Image build successful");
		System.out.println(result.getAbsolutePath());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

			
			//String curres="10k";
			
						
			String[] res={"200k","100k","50k","25k","20k","10k"};
			//for(String curres:res)
			String curres="100k";
			{
				System.out.println(curres);
				Mapbuilder mb=new Mapbuilder(curres, true);
				
				mb.buildMap_Control(true);
				//mb.buildMap();
				System.out.println(curres+" smallest col \t"+mb.smallest_col);
				System.out.println(curres+" largest col \t"+mb.largest_col);
				System.out.println(curres+" smallest f \t\t"+mb.smallest_f);
				System.out.println(curres+" largest f \t\t"+mb.largest_f);
				System.out.println(curres+" width \t\t"+mb.width);
				System.out.println(curres+" height \t\t"+mb.height);
				
				//mb.writeIMP();
				
				System.out.println("\n");
				
			}
			
			
			//mb.buildMap();
			
			
			
}
	
	/**
	 * select tiles of map
	 */
	private void getDim(){
		if(min){
			//select only tiles with data
			getMinDimEasy();
		}
		else
			//select all tiles, including empty ones
			getMaxDim();
	}
	
	/**
	 * get Map dimensions in Pixels, and find border rows/columns of image tile grid 
	 * @param curres
	 * @return
	 */
	private void getMinDim(){
		int smallest_col=Integer.MAX_VALUE;
		int largest_col=0;
		
		int smallest_f=Integer.MAX_VALUE;
		int largest_f=0;
		
		File root=new File(Constants.basePath+"raw"+File.separator+(Constants.map?"map":"ortho")+File.separator+curres+File.separator);//"F:\\tmp\\swiss_map_test\\"+curres+"\\");  //"+column+"\\"+row+".jpeg");
		int tmpsmall_col=0;
		for(File f:root.listFiles()){
			if(f.isDirectory()){
				try{
				    tmpsmall_col=Integer.parseInt(f.getName());
					
					//System.out.println("tmpsmal "+tmpsmall_col);
					boolean valid=false;
					int i=0;
					for(File m:f.listFiles()){
						//System.out.println("file l "+m.length());
						if(m.isFile() && m.length()>1500){
							valid=true;
							if(i<smallest_f){
								//System.out.println("smallest_f "+m.getName()+"  "+smallest_f);
								smallest_f=i;
							}
							if(i>largest_f)
								largest_f=i;
						}
						i++;
					}
					if(valid){
						if(tmpsmall_col<smallest_col)
							smallest_col=tmpsmall_col;
					}
					if(smallest_col<Integer.MAX_VALUE && (!valid)){
						largest_col=tmpsmall_col;
					}
				}catch (NumberFormatException e) {
					//ignore
				}	
			}
		}
		if(largest_col==0){
			largest_col=tmpsmall_col;
		}
					
		Constants.dimy_start.put(curres, smallest_f);
		Constants.dimx_start.put(curres, smallest_col);
		
		this.width=	(largest_col-smallest_col+1)*256; //width
		this.height=(largest_f-smallest_f+1)*256; //height
		this.largest_f=largest_f;		
		this.smallest_f=smallest_f;
		this.largest_col=largest_col;
		this.smallest_col=smallest_col;
	}
	
	private void getMinDimEasy(){
		
					
//		Constants.dimy_start.put(curres, smallest_f);
//		Constants.dimx_start.put(curres, smallest_col);
		
		this.width=	(Constants.dimx_end.get(curres)-Constants.dimx_start.get(curres)+1)*256; //width
		this.height=(Constants.dimy_end.get(curres)-Constants.dimy_start.get(curres)+1)*256; //height
		this.largest_f=Constants.dimy_end.get(curres);		
		this.smallest_f=Constants.dimy_start.get(curres);
		this.largest_col=Constants.dimx_end.get(curres);
		this.smallest_col=Constants.dimx_start.get(curres);
	}
	
	
	private void getMaxDim(){
		this.width=(Constants.dimx_end_max.get(curres)+1)*256; //width
		this.height=(Constants.dimy_end_max.get(curres)+1)*256; //height
		this.largest_f=Constants.dimy_end_max.get(curres);//largest_f;		
		this.smallest_f=0;
		this.largest_col=Constants.dimx_end_max.get(curres);//largest_col;
		this.smallest_col=0;
	}
	
	public void writeIMP(int tmpWidth, int tmpHeight, int row_from, int row_to, int col_from, int col_to, String nameExt){
		
		SwissCoordinate c1,c2,c3,c4;
		c1=Constants.origin.get(curres).getImgTileCo(col_from, row_to  , 1);//getScaleUpperLeftCo(min);
		c2=Constants.origin.get(curres).getImgTileCo(col_to  , row_to  , 2);//getScaleUpperRightCo(min);
		c3=Constants.origin.get(curres).getImgTileCo(col_from, row_from, 3);//.getScaleOriginCo(min);
		c4=Constants.origin.get(curres).getImgTileCo(col_to  , row_from, 4);//.getScaleLowerRightCo(min);
		
//		SwissCoordinate xc1,xc2,xc3,xc4;
//		xc1=Constants.origin.get(curres).getScaleUpperLeftCo(min);
//		xc2=Constants.origin.get(curres).getScaleUpperRightCo(min);
//		xc3=Constants.origin.get(curres).getScaleOriginCo(min);
//		xc4=Constants.origin.get(curres).getScaleLowerRightCo(min);
		
		System.out.println(nameExt+" 1 "+c1);
		//System.out.println("ok     1 "+xc1);
		System.out.println(nameExt+" 2 "+c2);
		//System.out.println("ok     2 "+xc2);
		System.out.println(nameExt+" 3 "+c3);
		//System.out.println("ok     3 "+xc3);
		System.out.println(nameExt+" 4 "+c4);
		//System.out.println("ok     4 "+xc4);
		
		
		File map=new File(file+nameExt+"."+Constants.fileFormat);
		if(!map.exists()){
			System.out.println("Map file not found, something went wrong");
		}
		
		System.out.println(				"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +
				"<Calibration>\r\n" +
				"P0=0.00000000,0.00000000,A,"+CoConvert.SwissgridToElipsoidCo(c1)+"\r\n" +	
				"P1="+(double)(tmpWidth-1)+",0.00000000,A,"+CoConvert.SwissgridToElipsoidCo(c2)+"\r\n" +
				"P2=0.00000000,"+(double)(tmpHeight-1)+",A,"+CoConvert.SwissgridToElipsoidCo(c3)+"\r\n" +
				"P3="+(double)(tmpWidth-1)+","+(double)(tmpHeight-1)+",A,"+CoConvert.SwissgridToElipsoidCo(c4)+"\r\n" +
				"</Calibration>"
		);
		
		
		String buf="CompeGPS MAP File\r\n" +
				"<Header>\r\n" +
				"Version=2\r\n" +
				"VerCompeGPS=7.1\r\n" +
				"Projection=14,Swiss Grid,\r\n" +
				"Coordinates=1\r\n" +
				"Datum=CH-1903\r\n" +
				"</Header>\r\n" +
				"<Map>\r\n" +
				"Bitmap="+map.getName()+"\r\n" +
				"BitsPerPixel=0\r\n" +
				"BitmapWidth="+tmpWidth+"\r\n" +
				"BitmapHeight="+tmpHeight+"\r\n" +
				"Type=10\r\n" +
				"</Map>\r\n" +
				"<Calibration>\r\n" +
				"P0=0.00000000,0.00000000,A,"+CoConvert.SwissgridToElipsoidCo(c1)+"\r\n" +	
				"P1="+(double)(tmpWidth-1)+",0.00000000,A,"+CoConvert.SwissgridToElipsoidCo(c2)+"\r\n" +
				"P2=0.00000000,"+(double)(tmpHeight-1)+",A,"+CoConvert.SwissgridToElipsoidCo(c3)+"\r\n" +
				"P3="+(double)(tmpWidth-1)+","+(double)(tmpHeight-1)+",A,"+CoConvert.SwissgridToElipsoidCo(c4)+"\r\n" +
				"</Calibration>";
		
		File imp=new File(this.file+nameExt+".imp");
		try {
			FileWriter fstream = new FileWriter(imp);
	        BufferedWriter out = new BufferedWriter(fstream);
	        out.write(buf);
	        out.close();
	        System.out.println("IMP file "+imp.getName()+" written!");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
	}
	
}


